package com.example.leetcode.simulation.common;

import java.util.*;

public class SimulationUtils {
    public static int reinitializePermutation(int n) {
        if (n <= 1) {
            return 0;
        }
        int[] ori = new int[n];
        int[] arr1 = new int[n];
        for (int i = 0; i < n; i++) {
            ori[i] = i;
            arr1[i] = i;
        }
        int[] arr2 = new int[n];
        int result = 0;
        while (true) {
            int[] arr = dealArray(arr1, arr2, result);
            result++;
            if (Arrays.equals(ori, arr)) {
                return result;
            }
        }
    }

    private static int[] dealArray(int[] arr1, int[] arr2, int result) {
        int n = arr1.length;
        if (result % 2 == 0) {
            return getInts(arr2, arr1, n);
        } else {
            return getInts(arr1, arr2, n);
        }
    }

    private static int[] getInts(int[] arr1, int[] arr2, int n) {
        for (int i = 0; i < n; i++) {
            if (i % 2 == 0) {
                arr1[i] = arr2[i / 2];
            } else {
                arr1[i] = arr2[n / 2 + (i - 1) / 2];
            }
        }
        return arr1;
    }

    public static int[] findingUsersActiveMinutes(int[][] logs, int k) {
        Map<Integer, Set<Integer>> map = new HashMap<>();
        Map<Integer, Integer> count = new HashMap<>();
        for (int[] log : logs) {
            int id = log[0];
            int time = log[1];
            Set<Integer> set = map.getOrDefault(id, new HashSet<>());
            set.add(time);
            map.put(id, set);
            count.put(id, set.size());
        }
        int[] result = new int[k];
        for (Integer id : count.keySet()) {
            Integer curCount = count.getOrDefault(id, 0);
            if (curCount >= 1 && curCount <= k + 1) {
                result[curCount - 1]++;
            }
        }
        return result;
    }

    public static double calculateTax(int[][] brackets, int income) {
        double result = 0;
        if (income < brackets[0][0]) {
            return income * 1.0 * brackets[0][1] / 100;
        }
        result += brackets[0][0] * brackets[0][1];
        for (int i = 0; i < brackets.length; i++) {
            if (income > brackets[i][0]) {
                int count;
                if (income <= brackets[i + 1][0]) {
                    count = income - brackets[i][0];
                } else {
                    count = brackets[i + 1][0] - brackets[i][0];
                }
                result += count * brackets[i + 1][1];
            }
        }
        return result / 100;
    }

    public static String alphabetBoardPath(String target) {
        int startX = 0, startY = 0;
        StringBuilder res = new StringBuilder();
        for (int i = 0; i < target.length(); i++) {
            char c = target.charAt(i);
            // 计算目标字符的坐标
            int targetX = (c - 'a') / 5;
            int targetY = (c - 'a') % 5;
            // 优先考虑左移兼容字母z
            if (targetX < startX) {
                for (int j = 0; j < startX - targetX; j++) {
                    res.append('U');
                }
            }
            // 优先考虑上移兼容字母z
            if (targetY < startY) {
                for (int j = 0; j < startY - targetY; j++) {
                    res.append('L');
                }
            }
            // 不需要左移才考虑右移
            if (targetX > startX) {
                for (int j = 0; j < targetX - startX; j++) {
                    res.append('D');
                }
            }
            // 不需要上移才考虑下移
            if (targetY > startY) {
                for (int j = 0; j < targetY - startY; j++) {
                    res.append('R');
                }
            }
            // 添加字符进路径
            res.append('!');
            // 更新起点
            startX = targetX;
            startY = targetY;
        }
        return res.toString();
    }

    public static String bestHand(int[] ranks, char[] suits) {
        Set<Character> suitsSet = new HashSet<Character>();
        for (char suit : suits) {
            suitsSet.add(suit);
        }
        if (suitsSet.size() == 1) {
            return "Flush";
        }
        Map<Integer, Integer> h = new HashMap<Integer, Integer>();
        for (int rank : ranks) {
            h.put(rank, h.getOrDefault(rank, 0) + 1);
        }
        if (h.size() == 5) {
            return "High Card";
        }
        for (Map.Entry<Integer, Integer> entry : h.entrySet()) {
            if (entry.getValue() > 2) {
                return "Three of a Kind";
            }
        }
        return "Pair";
    }

    public static boolean isRobotBounded(String instructions) {
        // 准备工作
        String east = "EAST";
        String north = "NORTH";
        String south = "SOUTH";
        String west = "WEST";
        int[] xDir = {0, 0, 1, -1};
        int[] yDir = {1, -1, 0, 0};
        Map<String, Integer> dirMap = new HashMap<>();
        dirMap.put(north, 0);
        dirMap.put(south, 1);
        dirMap.put(east, 2);
        dirMap.put(west, 3);

        // 开始模拟
        int curX = 0;
        int curY = 0;
        String curDir = north;
        for (char op : instructions.toCharArray()) {
            if (op == 'G') {
                Integer index = dirMap.get(curDir);
                curX += xDir[index];
                curY += yDir[index];
            } else if (op == 'L') {
                curDir = leftTurn(east, north, south, west, curDir);
            } else if (op == 'R') {
                curDir = rightTurn(east, north, south, west, curDir);
            }
        }

        return curX == 0 && curY == 0 || !curDir.equals(north);
    }

    private static String rightTurn(String east, String north, String south, String west, String curDir) {
        if (curDir.equals(east)) {
            curDir = south;
        } else if (curDir.equals(west)) {
            curDir = north;
        } else if (curDir.equals(north)) {
            curDir = east;
        } else {
            curDir = west;
        }
        return curDir;
    }

    private static String leftTurn(String east, String north, String south, String west, String curDir) {
        if (curDir.equals(east)) {
            curDir = north;
        } else if (curDir.equals(west)) {
            curDir = south;
        } else if (curDir.equals(north)) {
            curDir = west;
        } else {
            curDir = east;
        }
        return curDir;
    }
}
